home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gas_251.zip / bin_251 / bfd / nlm32-ppc.c < prev    next >
C/C++ Source or Header  |  1994-06-21  |  37KB  |  1,052 lines

  1. /* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
  2.    Copyright (C) 1994 Free Software Foundation, Inc.
  3.  
  4. This file is part of BFD, the Binary File Descriptor library.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "bfd.h"
  21. #include "sysdep.h"
  22. #include "libbfd.h"
  23.  
  24. /* The format of a PowerPC NLM changed.  Define OLDFORMAT to get the
  25.    old format.  */
  26.  
  27. #define ARCH_SIZE 32
  28.  
  29. #include "nlm/ppc-ext.h"
  30. #define Nlm_External_Fixed_Header    Nlm32_powerpc_External_Fixed_Header
  31.  
  32. #include "libnlm.h"
  33.  
  34. #ifdef OLDFORMAT
  35. static boolean nlm_powerpc_backend_object_p
  36.   PARAMS ((bfd *));
  37. static boolean nlm_powerpc_write_prefix
  38.   PARAMS ((bfd *));
  39. #endif
  40.  
  41. static boolean nlm_powerpc_read_reloc
  42.   PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
  43. static boolean nlm_powerpc_mangle_relocs
  44.   PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
  45. static boolean nlm_powerpc_read_import
  46.   PARAMS ((bfd *, nlmNAME(symbol_type) *));
  47.  
  48. #ifdef OLDFORMAT
  49. static boolean nlm_powerpc_write_reloc
  50.   PARAMS ((bfd *, asection *, arelent *, int));
  51. #endif
  52.  
  53. static boolean nlm_powerpc_write_import
  54.   PARAMS ((bfd *, asection *, arelent *));
  55. static boolean nlm_powerpc_write_external
  56.   PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
  57.  
  58. #ifndef OLDFORMAT
  59. static boolean nlm_powerpc_set_public_section
  60.   PARAMS ((bfd *, nlmNAME(symbol_type) *));
  61. static bfd_vma nlm_powerpc_get_public_offset
  62.   PARAMS ((bfd *, asymbol *));
  63. #endif
  64.  
  65. #ifdef OLDFORMAT
  66.  
  67. /* The prefix header is only used in the old format.  */
  68.  
  69. /* PowerPC NLM's have a prefix header before the standard NLM.  This
  70.    function reads it in, verifies the version, and seeks the bfd to
  71.    the location before the regular NLM header.  */
  72.  
  73. static boolean
  74. nlm_powerpc_backend_object_p (abfd)
  75.      bfd *abfd;
  76. {
  77.   struct nlm32_powerpc_external_prefix_header s;
  78.  
  79.   if (bfd_read ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
  80.     return false;
  81.  
  82.   if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
  83.       || bfd_h_get_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
  84.     return false;
  85.  
  86.   return true;
  87. }
  88.  
  89. /* Write out the prefix.  */
  90.  
  91. static boolean
  92. nlm_powerpc_write_prefix (abfd)
  93.      bfd *abfd;
  94. {
  95.   struct nlm32_powerpc_external_prefix_header s;
  96.  
  97.   memset (&s, 0, sizeof s);
  98.   memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
  99.   bfd_h_put_32 (abfd, (bfd_vma) NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
  100.   bfd_h_put_32 (abfd, (bfd_vma) 0, s.origins);
  101.  
  102.   /* FIXME: What should we do about the date?  */
  103.  
  104.   if (bfd_write ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
  105.     return false;
  106.  
  107.   return true;
  108. }
  109.  
  110. #endif /* OLDFORMAT */
  111.  
  112. #ifndef OLDFORMAT
  113.  
  114. /* There is only one type of reloc in a PowerPC NLM.  */
  115.  
  116. static reloc_howto_type nlm_powerpc_howto =
  117.   HOWTO (0,            /* type */
  118.      0,            /* rightshift */
  119.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  120.      32,            /* bitsize */
  121.      false,            /* pc_relative */
  122.      0,            /* bitpos */
  123.      complain_overflow_bitfield, /* complain_on_overflow */
  124.      0,            /* special_function */
  125.      "32",            /* name */
  126.      true,            /* partial_inplace */
  127.      0xffffffff,        /* src_mask */
  128.      0xffffffff,        /* dst_mask */
  129.      false);        /* pcrel_offset */
  130.  
  131. /* Read a PowerPC NLM reloc.  */
  132.  
  133. static boolean
  134. nlm_powerpc_read_reloc (abfd, sym, secp, rel)
  135.      bfd *abfd;
  136.      nlmNAME(symbol_type) *sym;
  137.      asection **secp;
  138.      arelent *rel;
  139. {
  140.   bfd_byte temp[4];
  141.   bfd_vma val;
  142.   const char *name;
  143.  
  144.   if (bfd_read (temp, sizeof (temp), 1, abfd) != sizeof (temp))
  145.     return false;
  146.  
  147.   val = bfd_get_32 (abfd, temp);
  148.  
  149.   /* The value is a word offset into either the code or data segment.
  150.      This is the location which needs to be adjusted.
  151.  
  152.      The high bit is 0 if the value is an offset into the data
  153.      segment, or 1 if the value is an offset into the text segment.
  154.  
  155.      If this is a relocation fixup rather than an imported symbol (the
  156.      sym argument is NULL), then the second most significant bit is 0
  157.      if the address of the data segment should be added to the
  158.      location addressed by the value, or 1 if the address of the text
  159.      segment should be added.
  160.  
  161.      If this is an imported symbol, the second most significant bit is
  162.      not used and must be 0.  */
  163.  
  164.   if ((val & NLM_HIBIT) == 0)
  165.     name = NLM_INITIALIZED_DATA_NAME;
  166.   else
  167.     {
  168.       name = NLM_CODE_NAME;
  169.       val &=~ NLM_HIBIT;
  170.     }
  171.   *secp = bfd_get_section_by_name (abfd, name);
  172.  
  173.   if (sym == NULL)
  174.     {
  175.       if ((val & (NLM_HIBIT >> 1)) == 0)
  176.     name = NLM_INITIALIZED_DATA_NAME;
  177.       else
  178.     {
  179.       name = NLM_CODE_NAME;
  180.       val &=~ (NLM_HIBIT >> 1);
  181.     }
  182.       rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
  183.     }
  184.  
  185.   rel->howto = &nlm_powerpc_howto;
  186.  
  187.   rel->address = val << 2;
  188.   rel->addend = 0;
  189.  
  190.   return true;
  191. }
  192.  
  193. #else /* OLDFORMAT */
  194.  
  195. /* This reloc handling is only applicable to the old format.  */
  196.  
  197. /* How to process the various reloc types.  PowerPC NLMs use XCOFF
  198.    reloc types, and I have just copied the XCOFF reloc table here.  */
  199.  
  200. static reloc_howto_type nlm_powerpc_howto_table[] =
  201. {
  202.   /* Standard 32 bit relocation.  */
  203.   HOWTO (0,                    /* type */                                 
  204.      0,                    /* rightshift */                           
  205.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  206.      32,                    /* bitsize */                   
  207.      false,                    /* pc_relative */                          
  208.      0,                    /* bitpos */                               
  209.      complain_overflow_bitfield, /* complain_on_overflow */
  210.      0,                /* special_function */                     
  211.      "R_POS",               /* name */                                 
  212.      true,                    /* partial_inplace */                      
  213.      0xffffffff,            /* src_mask */                             
  214.      0xffffffff,            /* dst_mask */                             
  215.      false),                /* pcrel_offset */
  216.  
  217.   /* 32 bit relocation, but store negative value.  */
  218.   HOWTO (1,                    /* type */                                 
  219.      0,                    /* rightshift */                           
  220.      -2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  221.      32,                    /* bitsize */                   
  222.      false,                    /* pc_relative */                          
  223.      0,                    /* bitpos */                               
  224.      complain_overflow_bitfield, /* complain_on_overflow */
  225.      0,                /* special_function */                     
  226.      "R_NEG",               /* name */                                 
  227.      true,                    /* partial_inplace */                      
  228.      0xffffffff,            /* src_mask */                             
  229.      0xffffffff,            /* dst_mask */                             
  230.      false),                /* pcrel_offset */
  231.  
  232.   /* 32 bit PC relative relocation.  */
  233.   HOWTO (2,                    /* type */                                 
  234.      0,                    /* rightshift */                           
  235.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  236.      32,                    /* bitsize */                   
  237.      true,                    /* pc_relative */                          
  238.      0,                    /* bitpos */                               
  239.      complain_overflow_signed, /* complain_on_overflow */
  240.      0,                /* special_function */                     
  241.      "R_REL",               /* name */                                 
  242.      true,                    /* partial_inplace */                      
  243.      0xffffffff,            /* src_mask */                             
  244.      0xffffffff,            /* dst_mask */                             
  245.      false),                /* pcrel_offset */
  246.   
  247.   /* 16 bit TOC relative relocation.  */
  248.   HOWTO (3,                    /* type */                                 
  249.      0,                    /* rightshift */                           
  250.      1,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  251.      16,                    /* bitsize */                   
  252.      false,                    /* pc_relative */                          
  253.      0,                    /* bitpos */                               
  254.      complain_overflow_signed, /* complain_on_overflow */
  255.      0,                /* special_function */                     
  256.      "R_TOC",               /* name */                                 
  257.      true,                    /* partial_inplace */                      
  258.      0xffff,            /* src_mask */                             
  259.      0xffff,            /* dst_mask */                             
  260.      false),                /* pcrel_offset */
  261.   
  262.   /* I don't really know what this is.  */
  263.   HOWTO (4,                    /* type */                                 
  264.      1,                    /* rightshift */                           
  265.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  266.      32,                    /* bitsize */                   
  267.      false,                    /* pc_relative */                          
  268.      0,                    /* bitpos */                               
  269.      complain_overflow_bitfield, /* complain_on_overflow */
  270.      0,                /* special_function */                     
  271.      "R_RTB",               /* name */                                 
  272.      true,                    /* partial_inplace */                      
  273.      0xffffffff,            /* src_mask */                             
  274.      0xffffffff,            /* dst_mask */                             
  275.      false),                /* pcrel_offset */
  276.   
  277.   /* External TOC relative symbol.  */
  278.   HOWTO (5,                    /* type */                                 
  279.      0,                    /* rightshift */                           
  280.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  281.      16,                    /* bitsize */                   
  282.      false,                    /* pc_relative */                          
  283.      0,                    /* bitpos */                               
  284.      complain_overflow_bitfield, /* complain_on_overflow */
  285.      0,                /* special_function */                     
  286.      "R_GL",                /* name */                                 
  287.      true,                    /* partial_inplace */                      
  288.      0xffff,            /* src_mask */                             
  289.      0xffff,            /* dst_mask */                             
  290.      false),                /* pcrel_offset */
  291.   
  292.   /* Local TOC relative symbol.  */
  293.   HOWTO (6,                    /* type */                                 
  294.      0,                    /* rightshift */                           
  295.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  296.      16,                    /* bitsize */                   
  297.      false,                    /* pc_relative */                          
  298.      0,                    /* bitpos */                               
  299.      complain_overflow_bitfield, /* complain_on_overflow */
  300.      0,                /* special_function */                     
  301.      "R_TCL",               /* name */                                 
  302.      true,                    /* partial_inplace */                      
  303.      0xffff,            /* src_mask */                             
  304.      0xffff,            /* dst_mask */                             
  305.      false),                /* pcrel_offset */
  306.   
  307.   { 7 },
  308.   
  309.   /* Non modifiable absolute branch.  */
  310.   HOWTO (8,                    /* type */                                 
  311.      0,                    /* rightshift */                           
  312.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  313.      26,                    /* bitsize */                   
  314.      false,                    /* pc_relative */                          
  315.      0,                    /* bitpos */                               
  316.      complain_overflow_bitfield, /* complain_on_overflow */
  317.      0,                /* special_function */                     
  318.      "R_BA",                /* name */                                 
  319.      true,                    /* partial_inplace */                      
  320.      0x3fffffc,            /* src_mask */                             
  321.      0x3fffffc,            /* dst_mask */                             
  322.      false),                /* pcrel_offset */
  323.   
  324.   { 9 },
  325.  
  326.   /* Non modifiable relative branch.  */
  327.   HOWTO (0xa,                    /* type */                                 
  328.      0,                    /* rightshift */                           
  329.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  330.      26,                    /* bitsize */                   
  331.      true,                    /* pc_relative */                          
  332.      0,                    /* bitpos */                               
  333.      complain_overflow_signed, /* complain_on_overflow */
  334.      0,                /* special_function */                     
  335.      "R_BR",                /* name */                                 
  336.      true,                    /* partial_inplace */                      
  337.      0x3fffffc,            /* src_mask */                             
  338.      0x3fffffc,            /* dst_mask */                             
  339.      false),                /* pcrel_offset */
  340.   
  341.   { 0xb },
  342.  
  343.   /* Indirect load.  */
  344.   HOWTO (0xc,                    /* type */                                 
  345.      0,                    /* rightshift */                           
  346.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  347.      16,                    /* bitsize */                   
  348.      false,                    /* pc_relative */                          
  349.      0,                    /* bitpos */                               
  350.      complain_overflow_bitfield, /* complain_on_overflow */
  351.      0,                /* special_function */                     
  352.      "R_RL",                /* name */                                 
  353.      true,                    /* partial_inplace */                      
  354.      0xffff,            /* src_mask */                             
  355.      0xffff,            /* dst_mask */                             
  356.      false),                /* pcrel_offset */
  357.   
  358.   /* Load address.  */
  359.   HOWTO (0xd,                    /* type */                                 
  360.      0,                    /* rightshift */                           
  361.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  362.      16,                    /* bitsize */                   
  363.      false,                    /* pc_relative */                          
  364.      0,                    /* bitpos */                               
  365.      complain_overflow_bitfield, /* complain_on_overflow */
  366.      0,                /* special_function */                     
  367.      "R_RLA",               /* name */                                 
  368.      true,                    /* partial_inplace */                      
  369.      0xffff,            /* src_mask */                             
  370.      0xffff,            /* dst_mask */                             
  371.      false),                /* pcrel_offset */
  372.   
  373.   { 0xe },
  374.   
  375.   /* Non-relocating reference.  */
  376.   HOWTO (0xf,                    /* type */                                 
  377.      0,                    /* rightshift */                           
  378.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  379.      32,                    /* bitsize */                   
  380.      false,                    /* pc_relative */                          
  381.      0,                    /* bitpos */                               
  382.      complain_overflow_bitfield, /* complain_on_overflow */
  383.      0,                /* special_function */                     
  384.      "R_REF",               /* name */                                 
  385.      false,                    /* partial_inplace */                      
  386.      0,                /* src_mask */                             
  387.      0,                /* dst_mask */                             
  388.      false),                /* pcrel_offset */
  389.   
  390.   { 0x10 },
  391.   { 0x11 },
  392.   
  393.   /* TOC relative indirect load.  */
  394.   HOWTO (0x12,                    /* type */                                 
  395.      0,                    /* rightshift */                           
  396.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  397.      16,                    /* bitsize */                   
  398.      false,                    /* pc_relative */                          
  399.      0,                    /* bitpos */                               
  400.      complain_overflow_bitfield, /* complain_on_overflow */
  401.      0,                /* special_function */                     
  402.      "R_TRL",               /* name */                                 
  403.      true,                    /* partial_inplace */                      
  404.      0xffff,            /* src_mask */                             
  405.      0xffff,            /* dst_mask */                             
  406.      false),                /* pcrel_offset */
  407.   
  408.   /* TOC relative load address.  */
  409.   HOWTO (0x13,                    /* type */                                 
  410.      0,                    /* rightshift */                           
  411.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  412.      16,                    /* bitsize */                   
  413.      false,                    /* pc_relative */                          
  414.      0,                    /* bitpos */                               
  415.      complain_overflow_bitfield, /* complain_on_overflow */
  416.      0,                /* special_function */                     
  417.      "R_TRLA",              /* name */                                 
  418.      true,                    /* partial_inplace */                      
  419.      0xffff,            /* src_mask */                             
  420.      0xffff,            /* dst_mask */                             
  421.      false),                /* pcrel_offset */
  422.   
  423.   /* Modifiable relative branch.  */
  424.   HOWTO (0x14,                    /* type */                                 
  425.      1,                    /* rightshift */                           
  426.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  427.      32,                    /* bitsize */                   
  428.      false,                    /* pc_relative */                          
  429.      0,                    /* bitpos */                               
  430.      complain_overflow_bitfield, /* complain_on_overflow */
  431.      0,                /* special_function */                     
  432.      "R_RRTBI",             /* name */                                 
  433.      true,                    /* partial_inplace */                      
  434.      0xffffffff,            /* src_mask */                             
  435.      0xffffffff,            /* dst_mask */                             
  436.      false),                /* pcrel_offset */
  437.   
  438.   /* Modifiable absolute branch.  */
  439.   HOWTO (0x15,                    /* type */                                 
  440.      1,                    /* rightshift */                           
  441.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  442.      32,                    /* bitsize */                   
  443.      false,                    /* pc_relative */                          
  444.      0,                    /* bitpos */                               
  445.      complain_overflow_bitfield, /* complain_on_overflow */
  446.      0,                /* special_function */                     
  447.      "R_RRTBA",             /* name */                                 
  448.      true,                    /* partial_inplace */                      
  449.      0xffffffff,            /* src_mask */                             
  450.      0xffffffff,            /* dst_mask */                             
  451.      false),                /* pcrel_offset */
  452.   
  453.   /* Modifiable call absolute indirect.  */
  454.   HOWTO (0x16,                    /* type */                                 
  455.      0,                    /* rightshift */                           
  456.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  457.      16,                    /* bitsize */                   
  458.      false,                    /* pc_relative */                          
  459.      0,                    /* bitpos */                               
  460.      complain_overflow_bitfield, /* complain_on_overflow */
  461.      0,                /* special_function */                     
  462.      "R_CAI",               /* name */                                 
  463.      true,                    /* partial_inplace */                      
  464.      0xffff,            /* src_mask */                             
  465.      0xffff,            /* dst_mask */                             
  466.      false),                /* pcrel_offset */
  467.   
  468.   /* Modifiable call relative.  */
  469.   HOWTO (0x17,                    /* type */                                 
  470.      0,                    /* rightshift */                           
  471.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  472.      16,                    /* bitsize */                   
  473.      false,                    /* pc_relative */                          
  474.      0,                    /* bitpos */                               
  475.      complain_overflow_bitfield, /* complain_on_overflow */
  476.      0,                /* special_function */                     
  477.      "R_REL",               /* name */                                 
  478.      true,                    /* partial_inplace */                      
  479.      0xffff,            /* src_mask */                             
  480.      0xffff,            /* dst_mask */                             
  481.      false),                /* pcrel_offset */
  482.   
  483.   /* Modifiable branch absolute.  */
  484.   HOWTO (0x18,                    /* type */                                 
  485.      0,                    /* rightshift */                           
  486.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  487.      16,                    /* bitsize */                   
  488.      false,                    /* pc_relative */                          
  489.      0,                    /* bitpos */                               
  490.      complain_overflow_bitfield, /* complain_on_overflow */
  491.      0,                /* special_function */                     
  492.      "R_RBA",               /* name */                                 
  493.      true,                    /* partial_inplace */                      
  494.      0xffff,            /* src_mask */                             
  495.      0xffff,            /* dst_mask */                             
  496.      false),                /* pcrel_offset */
  497.   
  498.   /* Modifiable branch absolute.  */
  499.   HOWTO (0x19,                    /* type */                                 
  500.      0,                    /* rightshift */                           
  501.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  502.      16,                    /* bitsize */                   
  503.      false,                    /* pc_relative */                          
  504.      0,                    /* bitpos */                               
  505.      complain_overflow_bitfield, /* complain_on_overflow */
  506.      0,                /* special_function */                     
  507.      "R_RBAC",              /* name */                                 
  508.      true,                    /* partial_inplace */                      
  509.      0xffff,            /* src_mask */                             
  510.      0xffff,            /* dst_mask */                             
  511.      false),                /* pcrel_offset */
  512.   
  513.   /* Modifiable branch relative.  */
  514.   HOWTO (0x1a,                    /* type */                                 
  515.      0,                    /* rightshift */                           
  516.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  517.      26,                    /* bitsize */                   
  518.      false,                    /* pc_relative */                          
  519.      0,                    /* bitpos */                               
  520.      complain_overflow_signed, /* complain_on_overflow */
  521.      0,                /* special_function */                     
  522.      "R_REL",               /* name */                                 
  523.      true,                    /* partial_inplace */                      
  524.      0xffff,            /* src_mask */                             
  525.      0xffff,            /* dst_mask */                             
  526.      false),                /* pcrel_offset */
  527.   
  528.   /* Modifiable branch absolute.  */
  529.   HOWTO (0x1b,                    /* type */                                 
  530.      0,                    /* rightshift */                           
  531.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  532.      16,                    /* bitsize */                   
  533.      false,                    /* pc_relative */                          
  534.      0,                    /* bitpos */                               
  535.      complain_overflow_bitfield, /* complain_on_overflow */
  536.      0,                /* special_function */                     
  537.      "R_REL",               /* name */                                 
  538.      true,                    /* partial_inplace */                      
  539.      0xffff,            /* src_mask */                             
  540.      0xffff,            /* dst_mask */                             
  541.      false)                 /* pcrel_offset */
  542. };
  543.  
  544. #define HOWTO_COUNT (sizeof nlm_powerpc_howto_table        \
  545.              / sizeof nlm_powerpc_howto_table[0])
  546.  
  547. /* Read a PowerPC NLM reloc.  */
  548.  
  549. static boolean
  550. nlm_powerpc_read_reloc (abfd, sym, secp, rel)
  551.      bfd *abfd;
  552.      nlmNAME(symbol_type) *sym;
  553.      asection **secp;
  554.      arelent *rel;
  555. {
  556.   struct nlm32_powerpc_external_reloc ext;
  557.   bfd_vma l_vaddr;
  558.   unsigned long l_symndx;
  559.   int l_rtype;
  560.   int l_rsecnm;
  561.   asection *code_sec, *data_sec, *bss_sec;
  562.  
  563.   /* Read the reloc from the file.  */
  564.   if (bfd_read (&ext, sizeof ext, 1, abfd) != sizeof ext)
  565.     return false;
  566.  
  567.   /* Swap in the fields.  */
  568.   l_vaddr = bfd_h_get_32 (abfd, ext.l_vaddr);
  569.   l_symndx = bfd_h_get_32 (abfd, ext.l_symndx);
  570.   l_rtype = bfd_h_get_16 (abfd, ext.l_rtype);
  571.   l_rsecnm = bfd_h_get_16 (abfd, ext.l_rsecnm);
  572.  
  573.   /* Get the sections now, for convenience.  */
  574.   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  575.   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  576.   bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
  577.  
  578.   /* Work out the arelent fields.  */
  579.   if (sym != NULL)
  580.     {
  581.       /* This is an import.  sym_ptr_ptr is filled in by
  582.      nlm_canonicalize_reloc.  */
  583.       rel->sym_ptr_ptr = NULL;
  584.     }
  585.   else
  586.     {
  587.       asection *sec;
  588.  
  589.       if (l_symndx == 0)
  590.     sec = code_sec;
  591.       else if (l_symndx == 1)
  592.     sec = data_sec;
  593.       else if (l_symndx == 2)
  594.     sec = bss_sec;
  595.       else
  596.     {
  597.       bfd_set_error (bfd_error_bad_value);
  598.       return false;
  599.     }
  600.  
  601.       rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
  602.     }
  603.  
  604.   rel->addend = 0;
  605.  
  606.   BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
  607.  
  608.   rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
  609.  
  610.   BFD_ASSERT (rel->howto->name != NULL
  611.           && ((l_rtype & 0x8000) != 0
  612.           ? (rel->howto->complain_on_overflow
  613.              == complain_overflow_signed)
  614.           : (rel->howto->complain_on_overflow
  615.              == complain_overflow_bitfield))
  616.           && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
  617.  
  618.   if (l_rsecnm == 0)
  619.     *secp = code_sec;
  620.   else if (l_rsecnm == 1)
  621.     {
  622.       *secp = data_sec;
  623.       l_vaddr -= bfd_section_size (abfd, code_sec);
  624.     }
  625.   else
  626.     {
  627.       bfd_set_error (bfd_error_bad_value);
  628.       return false;
  629.     }
  630.  
  631.   rel->address = l_vaddr;
  632.  
  633.   return true;
  634. }
  635.  
  636. #endif /* OLDFORMAT */
  637.  
  638. /* Mangle PowerPC NLM relocs for output.  */
  639.  
  640. static boolean
  641. nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count)
  642.      bfd *abfd;
  643.      asection *sec;
  644.      PTR data;
  645.      bfd_vma offset;
  646.      bfd_size_type count;
  647. {
  648.   return true;
  649. }
  650.  
  651. /* Read a PowerPC NLM import record */
  652.  
  653. static boolean
  654. nlm_powerpc_read_import (abfd, sym)
  655.      bfd *abfd;
  656.      nlmNAME(symbol_type) *sym;
  657. {
  658.   struct nlm_relent *nlm_relocs;    /* relocation records for symbol */
  659.   bfd_size_type rcount;            /* number of relocs */
  660.   bfd_byte temp[NLM_TARGET_LONG_SIZE];    /* temporary 32-bit value */
  661.   unsigned char symlength;        /* length of symbol name */
  662.   char *name;
  663.  
  664.   if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
  665.       != sizeof (symlength))
  666.     return (false);
  667.   sym -> symbol.the_bfd = abfd;
  668.   name = bfd_alloc (abfd, symlength + 1);
  669.   if (name == NULL)
  670.     {
  671.       bfd_set_error (bfd_error_no_memory);
  672.       return false;
  673.     }
  674.   if (bfd_read (name, symlength, 1, abfd) != symlength)
  675.     return (false);
  676.   name[symlength] = '\0';
  677.   sym -> symbol.name = name;
  678.   sym -> symbol.flags = 0;
  679.   sym -> symbol.value = 0;
  680.   sym -> symbol.section = bfd_und_section_ptr;
  681.   if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
  682.     return (false);
  683.   rcount = bfd_h_get_32 (abfd, temp);
  684.   nlm_relocs = ((struct nlm_relent *)
  685.         bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
  686.   if (nlm_relocs == (struct nlm_relent *) NULL)
  687.     {
  688.       bfd_set_error (bfd_error_no_memory);
  689.       return false;
  690.     }
  691.   sym -> relocs = nlm_relocs;
  692.   sym -> rcnt = 0;
  693.   while (sym -> rcnt < rcount)
  694.     {
  695.       asection *section;
  696.       
  697.       if (nlm_powerpc_read_reloc (abfd, sym, §ion,
  698.                   &nlm_relocs -> reloc)
  699.       == false)
  700.     return false;
  701.       nlm_relocs -> section = section;
  702.       nlm_relocs++;
  703.       sym -> rcnt++;
  704.     }
  705.   return true;
  706. }
  707.  
  708. #ifndef OLDFORMAT
  709.  
  710. /* Write a PowerPC NLM reloc.  */
  711.  
  712. static boolean
  713. nlm_powerpc_write_import (abfd, sec, rel)
  714.      bfd *abfd;
  715.      asection *sec;
  716.      arelent *rel;
  717. {
  718.   asymbol *sym;
  719.   bfd_vma val;
  720.   bfd_byte temp[4];
  721.  
  722.   /* PowerPC NetWare only supports one kind of reloc.  */
  723.   if (rel->addend != 0
  724.       || rel->howto == NULL
  725.       || rel->howto->rightshift != 0
  726.       || rel->howto->size != 2
  727.       || rel->howto->bitsize != 32
  728.       || rel->howto->bitpos != 0
  729.       || rel->howto->pc_relative
  730.       || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
  731.       || rel->howto->dst_mask != 0xffffffff)
  732.     {
  733.       bfd_set_error (bfd_error_invalid_operation);
  734.       return false;
  735.     }
  736.  
  737.   sym = *rel->sym_ptr_ptr;
  738.  
  739.   /* The value we write out is the offset into the appropriate
  740.      segment, rightshifted by two.  This offset is the section vma,
  741.      adjusted by the vma of the lowest section in that segment, plus
  742.      the address of the relocation.  */
  743.   val = bfd_get_section_vma (abfd, sec) + rel->address;
  744.   if ((val & 3) != 0)
  745.     {
  746.       bfd_set_error (bfd_error_bad_value);
  747.       return false;
  748.     }
  749.   val >>= 2;
  750.  
  751.   /* The high bit is 0 if the reloc is in the data section, or 1 if
  752.      the reloc is in the code section.  */
  753.   if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
  754.     val -= nlm_get_data_low (abfd);
  755.   else
  756.     {
  757.       val -= nlm_get_text_low (abfd);
  758.       val |= NLM_HIBIT;
  759.     }
  760.     
  761.   if (! bfd_is_und_section (bfd_get_section (sym)))
  762.     {
  763.       /* This is an internal relocation fixup.  The second most
  764.      significant bit is 0 if this is a reloc against the data
  765.      segment, or 1 if it is a reloc against the text segment.  */
  766.       if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
  767.     val |= NLM_HIBIT >> 1;
  768.     }
  769.  
  770.   bfd_put_32 (abfd, val, temp);
  771.   if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
  772.     return false;
  773.  
  774.   return true;
  775. }
  776.  
  777. #else /* OLDFORMAT */
  778.  
  779. /* This is used for the reloc handling in the old format.  */
  780.  
  781. /* Write a PowerPC NLM reloc.  */
  782.  
  783. static boolean
  784. nlm_powerpc_write_reloc (abfd, sec, rel, indx)
  785.      bfd *abfd;
  786.      asection *sec;
  787.      arelent *rel;
  788.      int indx;
  789. {
  790.   struct nlm32_powerpc_external_reloc ext;
  791.   asection *code_sec, *data_sec, *bss_sec;
  792.   asymbol *sym;
  793.   asection *symsec;
  794.   unsigned long l_symndx;
  795.   int l_rtype;
  796.   int l_rsecnm;
  797.   const reloc_howto_type *howto;
  798.   bfd_size_type address;
  799.  
  800.   /* Get the sections now, for convenience.  */
  801.   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  802.   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  803.   bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
  804.  
  805.   sym = *rel->sym_ptr_ptr;
  806.   symsec = bfd_get_section (sym);
  807.   if (indx != -1)
  808.     {
  809.       BFD_ASSERT (bfd_is_und_section (symsec));
  810.       l_symndx = indx + 3;
  811.     }
  812.   else
  813.     {
  814.       if (symsec == code_sec)
  815.     l_symndx = 0;
  816.       else if (symsec == data_sec)
  817.     l_symndx = 1;
  818.       else if (symsec == bss_sec)
  819.     l_symndx = 2;
  820.       else
  821.     {
  822.       bfd_set_error (bfd_error_bad_value);
  823.       return false;
  824.     }
  825.     }
  826.  
  827.   bfd_h_put_32 (abfd, (bfd_vma) l_symndx, ext.l_symndx);
  828.  
  829.   for (howto = nlm_powerpc_howto_table;
  830.        howto < nlm_powerpc_howto_table + HOWTO_COUNT;
  831.        howto++)
  832.     {
  833.       if (howto->rightshift == rel->howto->rightshift
  834.       && howto->size == rel->howto->size
  835.       && howto->bitsize == rel->howto->bitsize
  836.       && howto->pc_relative == rel->howto->pc_relative
  837.       && howto->bitpos == rel->howto->bitpos
  838.       && (howto->partial_inplace == rel->howto->partial_inplace
  839.           || (! rel->howto->partial_inplace
  840.           && rel->addend == 0))
  841.       && (howto->src_mask == rel->howto->src_mask
  842.           || (rel->howto->src_mask == 0
  843.           && rel->addend == 0))
  844.       && howto->dst_mask == rel->howto->dst_mask
  845.       && howto->pcrel_offset == rel->howto->pcrel_offset)
  846.     break;
  847.     }
  848.   if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
  849.     {
  850.       bfd_set_error (bfd_error_bad_value);
  851.       return false;
  852.     }
  853.  
  854.   l_rtype = howto->type;
  855.   if (howto->complain_on_overflow == complain_overflow_signed)
  856.     l_rtype |= 0x8000;
  857.   l_rtype |= (howto->bitsize - 1) << 8;
  858.   bfd_h_put_16 (abfd, (bfd_vma) l_rtype, ext.l_rtype);
  859.  
  860.   address = rel->address;
  861.  
  862.   if (sec == code_sec)
  863.     l_rsecnm = 0;
  864.   else if (sec == data_sec)
  865.     {
  866.       l_rsecnm = 1;
  867.       address += bfd_section_size (abfd, code_sec);
  868.     }
  869.   else
  870.     {
  871.       bfd_set_error (bfd_error_bad_value);
  872.       return false;
  873.     }
  874.  
  875.   bfd_h_put_16 (abfd, (bfd_vma) l_rsecnm, ext.l_rsecnm);
  876.   bfd_h_put_32 (abfd, (bfd_vma) address, ext.l_vaddr);
  877.  
  878.   if (bfd_write (&ext, sizeof ext, 1, abfd) != sizeof ext)
  879.     return false;
  880.  
  881.   return true;
  882. }
  883.  
  884. /* Write a PowerPC NLM import.  */
  885.  
  886. static boolean
  887. nlm_powerpc_write_import (abfd, sec, rel)
  888.      bfd *abfd;
  889.      asection *sec;
  890.      arelent *rel;
  891. {
  892.   return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
  893. }
  894.  
  895. #endif /* OLDFORMAT */
  896.  
  897. /* Write a PowerPC NLM external symbol.  This routine keeps a static
  898.    count of the symbol index.  FIXME: I don't know if this is
  899.    necessary, and the index never gets reset.  */
  900.  
  901. static boolean
  902. nlm_powerpc_write_external (abfd, count, sym, relocs)
  903.      bfd *abfd;
  904.      bfd_size_type count;
  905.      asymbol *sym;
  906.      struct reloc_and_sec *relocs;
  907. {
  908.   int i;
  909.   bfd_byte len;
  910.   unsigned char temp[NLM_TARGET_LONG_SIZE];
  911. #ifdef OLDFORMAT
  912.   static int indx;
  913. #endif
  914.  
  915.   len = strlen (sym->name);
  916.   if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
  917.       || bfd_write (sym->name, len, 1, abfd) != len)
  918.     return false;
  919.  
  920.   bfd_put_32 (abfd, count, temp);
  921.   if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
  922.     return false;
  923.  
  924.   for (i = 0; i < count; i++)
  925.     {
  926. #ifndef OLDFORMAT
  927.       if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
  928.     return false;
  929. #else
  930.       if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
  931.                      relocs[i].rel, indx))
  932.     return false;
  933. #endif
  934.     }
  935.  
  936. #ifdef OLDFORMAT
  937.   ++indx;
  938. #endif
  939.  
  940.   return true;
  941. }
  942.  
  943. #ifndef OLDFORMAT
  944.  
  945. /* PowerPC Netware uses a word offset, not a byte offset, for public
  946.    symbols.  */
  947.  
  948. /* Set the section for a public symbol.  */
  949.  
  950. static boolean
  951. nlm_powerpc_set_public_section (abfd, sym)
  952.      bfd *abfd;
  953.      nlmNAME(symbol_type) *sym;
  954. {
  955.   if (sym->symbol.value & NLM_HIBIT)
  956.     {
  957.       sym->symbol.value &= ~NLM_HIBIT;
  958.       sym->symbol.flags |= BSF_FUNCTION;
  959.       sym->symbol.section =
  960.     bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  961.     }
  962.   else
  963.     {
  964.       sym->symbol.section =
  965.     bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  966.     }
  967.  
  968.   sym->symbol.value <<= 2;
  969.  
  970.   return true;
  971. }
  972.  
  973. /* Get the offset to write out for a public symbol.  */
  974.  
  975. static bfd_vma
  976. nlm_powerpc_get_public_offset (abfd, sym)
  977.      bfd *abfd;
  978.      asymbol *sym;
  979. {
  980.   bfd_vma offset;
  981.   asection *sec;
  982.  
  983.   offset = bfd_asymbol_value (sym);
  984.   sec = bfd_get_section (sym);
  985.   if (sec->flags & SEC_CODE)
  986.     {
  987.       offset -= nlm_get_text_low (abfd);
  988.       offset |= NLM_HIBIT;
  989.     }
  990.   else if (sec->flags & (SEC_DATA | SEC_ALLOC))
  991.     {
  992.       /* SEC_ALLOC is for the .bss section.  */
  993.       offset -= nlm_get_data_low (abfd);
  994.     }
  995.   else
  996.     {
  997.       /* We can't handle an exported symbol that is not in the code or
  998.      data segment.  */
  999.       bfd_set_error (bfd_error_invalid_operation);
  1000.       /* FIXME: No way to return error.  */
  1001.       abort ();
  1002.     }
  1003.  
  1004.   return offset;
  1005. }
  1006.  
  1007. #endif /* ! defined (OLDFORMAT) */
  1008.  
  1009. #include "nlmswap.h"
  1010.  
  1011. static const struct nlm_backend_data nlm32_powerpc_backend =
  1012. {
  1013.   "NetWare PowerPC Module \032",
  1014.   sizeof (Nlm32_powerpc_External_Fixed_Header),
  1015. #ifndef OLDFORMAT
  1016.   0,    /* optional_prefix_size */
  1017. #else
  1018.   sizeof (struct nlm32_powerpc_external_prefix_header),
  1019. #endif
  1020.   bfd_arch_powerpc,
  1021.   0,
  1022.   false,
  1023. #ifndef OLDFORMAT
  1024.   0,    /* backend_object_p */
  1025.   0,    /* write_prefix */
  1026. #else
  1027.   nlm_powerpc_backend_object_p,
  1028.   nlm_powerpc_write_prefix,
  1029. #endif
  1030.   nlm_powerpc_read_reloc,
  1031.   nlm_powerpc_mangle_relocs,
  1032.   nlm_powerpc_read_import,
  1033.   nlm_powerpc_write_import,
  1034. #ifndef OLDFORMAT
  1035.   nlm_powerpc_set_public_section,
  1036.   nlm_powerpc_get_public_offset,
  1037. #else
  1038.   0,    /* set_public_section */
  1039.   0,    /* get_public_offset */
  1040. #endif
  1041.   nlm_swap_fixed_header_in,
  1042.   nlm_swap_fixed_header_out,
  1043.   nlm_powerpc_write_external,
  1044.   0,    /* write_export */
  1045. };
  1046.  
  1047. #define TARGET_BIG_NAME            "nlm32-powerpc"
  1048. #define TARGET_BIG_SYM            nlmNAME(powerpc_vec)
  1049. #define TARGET_BACKEND_DATA        &nlm32_powerpc_backend
  1050.  
  1051. #include "nlm-target.h"
  1052.